#pragma once

#include "Agent.h"
#include "Vector.h"
#include "Space.h"
#include "Observer.h"
#include <string>
#include "SpaceNode.h"
#include "CircleNode.h"
/*
  Copyright 2008 by Alexey Solovyev and University of Pittsburgh
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/

namespace org
{
	namespace spark
	{
		namespace space
		{


			using org::spark::core::Agent;
			using org::spark::core::Observer;
			using org::spark::math::Vector;
			//using org::spark::math::Vector4d;



			/// <summary>
			/// The basic space agent class 
			/// </summary>
			class SpaceAgent : public Agent
			{
				/// <summary>
				/// Serial version UID
				/// </summary>
			private:
				//static const long long serialVersionUID = 1LL;

				// The space node which determines the position of the agent
			protected:
				SpaceNode *node;

				// A label of the agent
				std::string label;

			public:
				static const int CIRCLE = 1;
				static const int SQUARE = 2;
				static const int TORUS = 3;
				static const int SQUARE2 = 6;
				// Experimental flags for physical nodes
				static const int DYNAMIC_CIRCLE = 4;
				static const int STATIC_CIRCLE = 5;

				static Vector *const BLACK;
				static Vector *const WHITE;
				static Vector *const BLUE;
				static Vector *const GREEN;
				static Vector *const RED;
				static Vector *const CYAN;
				static Vector *const YELLOW;
				static Vector *const MAGENTA;
				static Vector *const GREY;

			private:
				int type;

			public:
				virtual int getType();

				/// <summary>
				/// Creates a space agent in the specific space
				/// with the given size and shape.
				/// @space </summary>
				/// <param name="r"> </param>
				/// <param name="type"> </param>
				SpaceAgent(Space *space, double r, int type);


				/// <summary>
				/// Creates a space agent in a default space
				/// with the given size and shape </summary>
				/// <param name="r"> </param>
				/// <param name="type"> </param>
// Calls to same-class constructors are not supported in C++ prior to C++11:
				SpaceAgent(double r, int type); //this(Observer.getDefaultSpace(), r, type);


				/// <summary>
				/// Creates the space agent with the circle space node of the radius r </summary>
				/// <param name="r"> </param>
// Calls to same-class constructors are not supported in C++ prior to C++11:
				SpaceAgent(double r); //this(r, CIRCLE);

				/// <summary>
				/// Creates the space agent with the circle space node of the radius 1.0
				/// </summary>
// Calls to same-class constructors are not supported in C++ prior to C++11:
				SpaceAgent(); //this(1.0);


				/// <summary>
				/// Moves the agent to the position v </summary>
				/// <param name="v"> new position </param>
				virtual void jump(Vector *v);

				/// <summary>
				/// Moves the agent to the position v </summary>
				/// <param name="v">
				/// Use jump instead this method </param>
				virtual void moveTo(Vector *v);

				/// <summary>
				/// Changes the position of the agent by the vector v </summary>
				/// <param name="v"> </param>
				virtual void move(Vector *v);


				/// <summary>
				/// Moves the agent to the random position
				/// </summary>
				virtual void setRandomPosition();

				/// <summary>
				/// Removes the agent from the space and the context
				/// </summary>
				virtual void die();


				/// <summary>
				/// Moves the agent into a new space and 
				/// to a new position inside this space. </summary>
				/// <param name="space"> </param>
				/// <param name="pos">
				/// Note: does not work in parallel execution mode correctly </param>
				virtual void moveToSpace(Space *space, Vector *pos);


				/// <summary>
				/// Returns the relative size (radius for circle node) of the agent
				/// @return
				/// </summary>
				virtual double getRelativeSize();

				/// <summary>
				/// Gets the position of the agent
				/// @return
				/// </summary>
				virtual Vector *getPosition();

				/// <summary>
				/// Gets the space node of this agent </summary>
				/// <returns> space node </returns>
				virtual SpaceNode *getNode();


				/// <summary>
				/// Returns the space in which the agent exists
				/// @return
				/// </summary>
				virtual Space *getSpace();


				/// <summary>
				/// Sets the agent's label </summary>
				/// <param name="label"> </param>
				virtual void setLabel(const std::string &label);


				/// <summary>
				/// Returns the agent's label
				/// @return
				/// </summary>
				virtual std::string getLabel();


				/// <summary>
				/// Sets the color of the agent </summary>
				/// <param name="c"> new color </param>
				//virtual void setColor(Vector *c);

				/// <summary>
				/// Sets the color of the agent </summary>
				/// <param name="c"> new color </param>
				//virtual void setColor(Vector4d *c);


				/// <summary>
				/// Gets the color of the agent </summary>
				/// <returns> color </returns>
				//virtual Vector4d *getColor();


				//virtual Vector *getRGBColor();


				/// <summary>
				/// Custom deserialization is needed.
				/// </summary>
			private:
				//void readObject(ObjectInputStream *ois); //throw(IOException, ClassNotFoundException);

				/// <summary>
				/// Custom serialization is needed.
				/// </summary>
				//void writeObject(ObjectOutputStream *oos); //throw(IOException);


			private:
				void InitializeInstanceFields();
			};

		}
	}
}
